using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace Meta.Basic2D
{
	/// <summary>
	/// Summary description for DisplayWindow.
	/// </summary>
	public class DisplayWindow : System.Windows.Forms.Form
	{
		//
		// Instance variables
		//

		public Picture picture;
		bool[] keyState = new bool[256];

		// Animation stuff
		bool animate;
		int updateRate=30;
		Timer repaintTimer;
		public Meta.Procedure beforeRedraw=null;

		public bool Animate {
			get {
				return animate;
			}
			set {
				animate = value;
				if (animate && Visible)
					repaintTimer.Start();
				else
					repaintTimer.Stop();
			}
		}

		protected override void OnVisibleChanged(EventArgs e) {
			repaintTimer.Enabled = Visible && Animate;
			base.OnVisibleChanged (e);
		}


		public int UpdateRate {
			get {
				return updateRate;
			}
			set {
				updateRate = value;
				repaintTimer.Interval = System.Math.Max(1000/updateRate, 1);
			}
		}


		public DisplayWindow(Picture picture) {
			this.picture = picture;
			repaintTimer = new Timer();
			repaintTimer.Tick += new EventHandler(NextAnimationFrame);
			UpdateRate = 30;
			SetStyle(ControlStyles.AllPaintingInWmPaint|ControlStyles.DoubleBuffer|ControlStyles.UserPaint, true);
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();
		}

		//
		// Redraw logic
		//

		protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) {
			e.Graphics.Clear(Color.White);
			picture.Render(e.Graphics, Pens.Black, null);
		}

		void NextAnimationFrame(object sender, EventArgs e) {
			if (Animate)
				repaintTimer.Start();
			if (beforeRedraw!=null) {
				if (Meta.TopLevel.CurrentThreadTopLevel.CallWithErrorHandler(beforeRedraw, repaintTimer.Interval/1000.0F) is Exception) {
					Animate=false;
					return;
				}
			}
			ForceRedraw();
		}

		void ForceRedraw() {
			Refresh();
		}

		//
		// Keyboard handling
		//

		protected override void OnKeyDown(KeyEventArgs e) {
			keyState[(byte)e.KeyCode] = true;
			e.Handled=true;
		}
		protected override void OnKeyUp(KeyEventArgs e) {
			keyState[(byte)e.KeyCode] = false;
			e.Handled=true;
		}
		public bool IsKeyDown(byte k) {
			return keyState[(byte)k];
		}
		public bool UpPressed {
			get {
				return keyState[(byte)Keys.Up];
			}
		}
		public bool DownPressed {
			get {
				return keyState[(byte)Keys.Down];
			}
		}
		public bool LeftPressed {
			get {
				return keyState[(byte)Keys.Left];
			}
		}
		public bool RightPressed {
			get {
				return keyState[(byte)Keys.Right];
			}
		}



		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;
		private System.Windows.Forms.MainMenu mainMenu1;
		private System.Windows.Forms.MenuItem fileMenuItem;
		private System.Windows.Forms.MenuItem closeMenuItem;
		private System.Windows.Forms.MenuItem animationMenuItem;
		private System.Windows.Forms.MenuItem redrawMenuItem;
		private System.Windows.Forms.MenuItem animateMenuItem;
		private System.Windows.Forms.MenuItem updateRateMenuItem;
		private System.Windows.Forms.MenuItem u1MenuItem;
		private System.Windows.Forms.MenuItem u2MenuItem;
		private System.Windows.Forms.MenuItem u5MenuItem;
		private System.Windows.Forms.MenuItem u10MenuItem;
		private System.Windows.Forms.MenuItem u30MenuItem;
		private System.Windows.Forms.MenuItem u60MenuItem;
		private System.Windows.Forms.MenuItem uInfiniteMenuItem;
	

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.mainMenu1 = new System.Windows.Forms.MainMenu();
			this.fileMenuItem = new System.Windows.Forms.MenuItem();
			this.closeMenuItem = new System.Windows.Forms.MenuItem();
			this.animationMenuItem = new System.Windows.Forms.MenuItem();
			this.animateMenuItem = new System.Windows.Forms.MenuItem();
			this.redrawMenuItem = new System.Windows.Forms.MenuItem();
			this.updateRateMenuItem = new System.Windows.Forms.MenuItem();
			this.u1MenuItem = new System.Windows.Forms.MenuItem();
			this.u2MenuItem = new System.Windows.Forms.MenuItem();
			this.u5MenuItem = new System.Windows.Forms.MenuItem();
			this.u10MenuItem = new System.Windows.Forms.MenuItem();
			this.u30MenuItem = new System.Windows.Forms.MenuItem();
			this.u60MenuItem = new System.Windows.Forms.MenuItem();
			this.uInfiniteMenuItem = new System.Windows.Forms.MenuItem();
			// 
			// mainMenu1
			// 
			this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																					  this.fileMenuItem,
																					  this.animationMenuItem});
			// 
			// fileMenuItem
			// 
			this.fileMenuItem.Index = 0;
			this.fileMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																						 this.closeMenuItem});
			this.fileMenuItem.Text = "&File";
			// 
			// closeMenuItem
			// 
			this.closeMenuItem.Index = 0;
			this.closeMenuItem.Text = "&Close";
			this.closeMenuItem.Click += new System.EventHandler(this.closeMenuItem_Click);
			// 
			// animationMenuItem
			// 
			this.animationMenuItem.Index = 1;
			this.animationMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																							  this.animateMenuItem,
																							  this.redrawMenuItem,
																							  this.updateRateMenuItem});
			this.animationMenuItem.Text = "&Animation";
			this.animationMenuItem.Popup += new System.EventHandler(this.animationMenuItem_Popup);
			// 
			// animateMenuItem
			// 
			this.animateMenuItem.Index = 0;
			this.animateMenuItem.Text = "&Animate";
			this.animateMenuItem.Click += new System.EventHandler(this.animateMenuItem_Click);
			// 
			// redrawMenuItem
			// 
			this.redrawMenuItem.Index = 1;
			this.redrawMenuItem.Text = "&Redraw once";
			this.redrawMenuItem.Click += new System.EventHandler(this.redrawMenuItem_Click);
			// 
			// updateRateMenuItem
			// 
			this.updateRateMenuItem.Index = 2;
			this.updateRateMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																							   this.u1MenuItem,
																							   this.u2MenuItem,
																							   this.u5MenuItem,
																							   this.u10MenuItem,
																							   this.u30MenuItem,
																							   this.u60MenuItem,
																							   this.uInfiniteMenuItem});
			this.updateRateMenuItem.Text = "&Update rate";
			this.updateRateMenuItem.Popup += new System.EventHandler(this.updateRateMenuItem_Popup);
			// 
			// u1MenuItem
			// 
			this.u1MenuItem.Index = 0;
			this.u1MenuItem.Text = "1";
			this.u1MenuItem.Click += new System.EventHandler(this.u1MenuItem_Click);
			// 
			// u2MenuItem
			// 
			this.u2MenuItem.Index = 1;
			this.u2MenuItem.Text = "2";
			this.u2MenuItem.Click += new System.EventHandler(this.u2MenuItem_Click);
			// 
			// u5MenuItem
			// 
			this.u5MenuItem.Index = 2;
			this.u5MenuItem.Text = "5";
			this.u5MenuItem.Click += new System.EventHandler(this.u5MenuItem_Click);
			// 
			// u10MenuItem
			// 
			this.u10MenuItem.Index = 3;
			this.u10MenuItem.Text = "10";
			this.u10MenuItem.Click += new System.EventHandler(this.u10MenuItem_Click);
			// 
			// u30MenuItem
			// 
			this.u30MenuItem.Index = 4;
			this.u30MenuItem.Text = "30";
			this.u30MenuItem.Click += new System.EventHandler(this.u30MenuItem_Click);
			// 
			// u60MenuItem
			// 
			this.u60MenuItem.Index = 5;
			this.u60MenuItem.Text = "60";
			this.u60MenuItem.Click += new System.EventHandler(this.u60MenuItem_Click);
			// 
			// uInfiniteMenuItem
			// 
			this.uInfiniteMenuItem.Index = 6;
			this.uInfiniteMenuItem.Text = "infinite";
			this.uInfiniteMenuItem.Click += new System.EventHandler(this.uInfiniteMenuItem_Click);
			// 
			// DisplayWindow
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(464, 422);
			this.Menu = this.mainMenu1;
			this.Name = "DisplayWindow";
			this.Text = "DisplayWindow";
		}
		#endregion

		private void closeMenuItem_Click(object sender, System.EventArgs e) {
			Close();
		}

		private void animateMenuItem_Click(object sender, System.EventArgs e) {
			Animate = !Animate;
		}

		private void redrawMenuItem_Click(object sender, System.EventArgs e) {
			ForceRedraw();
		}

		private void animationMenuItem_Popup(object sender, System.EventArgs e) {
			animateMenuItem.Checked = Animate;
		}

		private void u1MenuItem_Click(object sender, System.EventArgs e) {
			UpdateRate=1;
		}

		private void u2MenuItem_Click(object sender, System.EventArgs e) {
			UpdateRate=2;
		}

		private void u5MenuItem_Click(object sender, System.EventArgs e) {
			UpdateRate=5;
		}

		private void u10MenuItem_Click(object sender, System.EventArgs e) {
			UpdateRate=10;
		}

		private void u30MenuItem_Click(object sender, System.EventArgs e) {
			UpdateRate=30;
		}

		private void u60MenuItem_Click(object sender, System.EventArgs e) {
			UpdateRate=60;
		}

		private void uInfiniteMenuItem_Click(object sender, System.EventArgs e) {
			UpdateRate=10000;
		}

		private void updateRateMenuItem_Popup(object sender, System.EventArgs e) {
			int i = UpdateRate;
			u1MenuItem.Checked = (i==1);
			u2MenuItem.Checked = (i==2);
			u5MenuItem.Checked = (i==5);
			u10MenuItem.Checked = (i==10);
			u30MenuItem.Checked = (i==30);
			u60MenuItem.Checked = (i==60);
			uInfiniteMenuItem.Checked = i>500;
		}
	}
}
